package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.service.SetmealDishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Mylinja 2021-12-16 星期四 21:39
 */
@Slf4j
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private SetmealDishService setmealDishService;

    /**
     * 新增菜品，同时保存对应的口味数据
     *
     * @param dishDto 菜品dto类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveWithFlavor(DishDto dishDto) {
        //①. 保存菜品基本信息 ;
        this.save(dishDto);

        //②. 获取保存的菜品ID ;
        Long id = dishDto.getId();

        //③. 获取菜品口味列表，遍历列表，为菜品口味对象属性dishId赋值;
        List<DishFlavor> flavors = dishDto.getFlavors();
        for (DishFlavor flavor : flavors) {
            log.info("设置菜品id");
            flavor.setDishId(id);

        }

        //④. 批量保存菜品口味列表;
        dishFlavorService.saveBatch(flavors);

    }

    /**
     * 重写查询菜品方法
     *
     * @param id 需要回显的菜品id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DishDto getByIdWithFlavor(long id) {
        //1 先查询出dish对象
        Dish dish = this.getById(id);
        DishDto dishDto = new DishDto();

        BeanUtils.copyProperties(dish, dishDto);

        //2 根据菜品id，去菜品口味表中，查询对应的口味信息（list集合）
        LambdaQueryWrapper<DishFlavor> query = new LambdaQueryWrapper<>();
        query.eq(DishFlavor::getDishId, id);
        List<DishFlavor> list = dishFlavorService.list(query);
        dishDto.setFlavors(list);

        //3 返回对象
        return dishDto;
    }

    /**
     * 重写更新菜品方法
     * <p>
     * 在该方法中，我们既需要更新dish菜品基本信息表，还需要更新dish_flavor菜品口味表。
     * 而页面再操作时，关于菜品的口味，有修改，有新增，也有可能删除，
     * 我们应该如何更新菜品口味信息呢？
     * 其实，无论菜品口味信息如何变化，我们只需要保持一个原则：
     * <先删除，后添加。>
     * </p>
     *
     * @param dishDto dishDto对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateByIdWithFlavor(DishDto dishDto) {
        //1 先更新dish表中的菜品
        this.updateById(dishDto);

        //2 删除dish_flavor表中的菜品口味信息
        LambdaQueryWrapper<DishFlavor> query = new LambdaQueryWrapper<>();
        query.eq(DishFlavor::getDishId, dishDto.getId());
        dishFlavorService.remove(query);

        //3 然后拿到flavors中的list集合,重新保存到dish_flavor表中
        List<DishFlavor> flavors = dishDto.getFlavors();
        // 断点调试之后发现，此时flavors集合里面的每个DishFlavor对象，只有name，value属性
        // 需要自己赋值dishId属性
        flavors = flavors.stream().peek((dishFlavor) ->
                dishFlavor.setDishId(dishDto.getId())
        ).collect(Collectors.toList());

        dishFlavorService.saveBatch(flavors);
    }

    /**
     * 批量删除菜品方法
     *
     * @param ids 删除菜品的ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(List<Long> ids) {
        //A. 查询该菜品是否关联了套餐，如果关联了套餐，就不能删除
        // SQL: select count(*) from setmeal_dish where id in(1,2,3,4...) and status = 1;
        // 这里的这个query条件查询器是为了去查找的
        LambdaQueryWrapper<SetmealDish> query1 = new LambdaQueryWrapper<>();
        query1.in(SetmealDish::getDishId, ids);

        // 开始查询
        int count = setmealDishService.count(query1);
        if (count > 0) {
            // 不能删除
            throw new CustomException("该菜品关联了套餐，请先删除套餐...");
        }

        //B. 查询该菜品是否在售，在售状态不能删除
        LambdaQueryWrapper<Dish> query2 = new LambdaQueryWrapper<>();
        query2.eq(Dish::getStatus, 1);
        int count1 = this.count(query2);
        if (count1 > 0) {
            // 不能删除
            throw new CustomException("菜品正在售卖中，不能删除...");
        }

        //C. 删除菜品表中的菜品和口味表中菜品对应的口味
        //SQL: delete from Dish where id in (1,2,3)
        this.removeByIds(ids);

        //SQL：delete from Dish_flavor where dish_id in (1,2,3)
        LambdaQueryWrapper<DishFlavor> query3 = new LambdaQueryWrapper<>();
        query3.eq(DishFlavor::getDishId, ids);
        dishFlavorService.remove(query3);
    }

}
